// 这是角色选择弹窗，当前里面放的是图片，后期需要修改为视频，截取首帧做封面 
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { request } from '@/utils/request';
import { useI18n, toApiLanguageCode } from '@/utils/in18';

// 角色选择子组件

type CategoryType = 'real_male' | 'real_female' | 'anime_male' | 'anime_female' | '';
type RaceType = 'persion' | 'other' | '';

interface TemplateItem {
    id?: number;
    name?: string;
    image_url?: string;
    role_prompt?: string;
    // 新增 category 字段，从后端返回
    category?: string;
}

interface ApiListResponse<T> {
    success: boolean;
    data: T[];
    total?: number;
    page?: number;
    page_size?: number;
}

const PAGE_SIZE = 10; // 接口要求每页 4 条

interface SelectPersionProps {
    // 选择回调：在作为弹窗使用时由父组件传入
    onSelect?: (item: TemplateItem) => void;
    // 关闭回调
    onClose?: () => void;
}

const SelectPersion: React.FC<SelectPersionProps> = ({ onSelect, onClose }) => {
    const navigate = useNavigate();
    const { locale, t } = useI18n();
    type TabType = 'liked' | 'official';
    const [tab, setTab] = React.useState<TabType>('liked'); // 默认优先展示我喜欢的

    // 动态生成国际化的选项
    const categoryOptions: { value: CategoryType; label: string }[] = [
        { value: 'real_male', label: t('CreatImg.category_real_male') },
        { value: 'real_female', label: t('CreatImg.category_real_female') },
        { value: 'anime_male', label: t('CreatImg.category_anime_male') },
        { value: 'anime_female', label: t('CreatImg.category_anime_female') },
    ];

    const raceOptions: { value: RaceType; label: string }[] = [
        { value: 'persion', label: t('CreatImg.race_persion') },
        { value: 'other', label: t('CreatImg.race_other') },
    ];

    // 查询参数状态（仅官方）
    const [category, setCategory] = React.useState<CategoryType>('');
    const [race, setRace] = React.useState<RaceType>('');
    const [page, setPage] = React.useState(1);

    // 官方列表状态
    const [items, setItems] = React.useState<TemplateItem[]>([]);
    const [total, setTotal] = React.useState(0);
    const [loading, setLoading] = React.useState(false);

    // 我喜欢的列表状态
    const [likedItems, setLikedItems] = React.useState<TemplateItem[]>([]);
    const [likedTotal, setLikedTotal] = React.useState(0);
    const [likedPage, setLikedPage] = React.useState(1);
    const [likedLoading, setLikedLoading] = React.useState(false);
    // 是否还有更多（按 Tab 独立维护），避免依赖 total 为空导致不翻页
    const [hasMoreOfficial, setHasMoreOfficial] = React.useState(true);
    const [hasMoreLiked, setHasMoreLiked] = React.useState(true);
    const scrollRef = React.useRef<HTMLDivElement | null>(null);
    const fetchingOfficialRef = React.useRef(false);
    const fetchingLikedRef = React.useRef(false);
    const sentinelRef = React.useRef<HTMLDivElement | null>(null);
    // 按 Tab 维护独立的初始化完成标志，避免某一 Tab 的初始化状态影响另一 Tab
    const initializedOfficialRef = React.useRef(false);
    const initializedLikedRef = React.useRef(false);
    const lastRequestIdRef = React.useRef(0); // 忽略过期请求，防止乱序导致的闪烁/重复（官方）
    const lastLikedRequestIdRef = React.useRef(0); // 忽略过期请求（我喜欢的）
    
    // 工具方法：判断 sentinel 是否在可视范围内（考虑与 IO 相同的 rootMargin）
    const isSentinelVisible = React.useCallback(() => {
        const root = scrollRef.current;
        const sentinel = sentinelRef.current;
        if (!root || !sentinel) return false;
        const rootRect = root.getBoundingClientRect();
        const sentinelRect = sentinel.getBoundingClientRect();
        const margin = 120; // 与 IO rootMargin 对齐
        const verticallyVisible = sentinelRect.top <= rootRect.bottom + margin && sentinelRect.bottom >= rootRect.top - margin;
        const horizontallyVisible = sentinelRect.left <= rootRect.right && sentinelRect.right >= rootRect.left;
        return verticallyVisible && horizontallyVisible;
    }, []);

    // 主动检查并触发下一页加载（解决首次进入时序导致的 IO 未触发问题）
    const tryLoadMore = React.useCallback(() => {
        const onLiked = tab === 'liked';
        const hasMore = onLiked ? hasMoreLiked : hasMoreOfficial;
        const isLoading = onLiked ? likedLoading : loading;
        const fetching = onLiked ? fetchingLikedRef.current : fetchingOfficialRef.current;
        const initialized = onLiked ? initializedLikedRef.current : initializedOfficialRef.current;
        if (initialized && hasMore && !isLoading && !fetching && isSentinelVisible()) {
            if (onLiked) {
                setLikedPage((p) => p + 1);
            } else {
                setPage((p) => p + 1);
            }
        }
    }, [tab, hasMoreLiked, hasMoreOfficial, likedLoading, loading, isSentinelVisible]);

    // 兜底：基于 scroll 的接近底部检测（含简单节流）
    const lastScrollTriggerAtRef = React.useRef(0);
    React.useEffect(() => {
        const root = scrollRef.current;
        if (!root) return;
        const onScroll = () => {
            const now = Date.now();
            if (now - lastScrollTriggerAtRef.current < 250) return; // 节流 250ms
            const distanceToBottom = root.scrollHeight - root.scrollTop - root.clientHeight;
            if (distanceToBottom <= 240) { // 接近底部
                lastScrollTriggerAtRef.current = now;
                tryLoadMore();
            }
        };
        root.addEventListener('scroll', onScroll, { passive: true });
        return () => root.removeEventListener('scroll', onScroll as any);
    }, [tryLoadMore, tab]);

    // 请求函数（官方）：根据当前筛选与分页请求列表
    const fetchList = React.useCallback(async () => {
        const currentRequestId = ++lastRequestIdRef.current;
        setLoading(true);
        fetchingOfficialRef.current = true;
        try {
            // 语言参数由 axios 拦截器自动注入，此处仍按需求显式传参以更安全
            const res = await request.post<ApiListResponse<TemplateItem>>(
                '/api/template/getTemplatesRoute',
                {
                    category: category || '',
                    race: race || '',
                    origin: '',
                    name: '',
                    sort: 'likes',
                    page,
                    page_size: PAGE_SIZE,
                    // 语言按产品约定：xby(西) fy(法) jp(日) en(英) ey(俄)
                    language: toApiLanguageCode(locale as any),
                    information: ['role_prompt', 'image_url', 'name'],
                }
            );
            const { data, total: t = 0 } = res?.data || ({} as any);
            const list = Array.isArray(data) ? data : [];

            // 仅处理最新请求的结果，忽略过期响应
            if (currentRequestId !== lastRequestIdRef.current) return;

            setItems((prev) => {
                const merged = page === 1 ? list : [...prev, ...list];
                // 依据 id 优先去重，其次使用 image_url/name 兜底，避免重复闪烁
                const seen = new Set<string | number>();
                const deduped: TemplateItem[] = [];
                for (const item of merged) {
                    const key = (item.id ?? item.image_url ?? item.name ?? '') as any;
                    if (!seen.has(key)) {
                        seen.add(key);
                        deduped.push(item);
                    }
                }
                return deduped;
            });
            setTotal(t || 0);
            // 计算是否还有更多（优先使用 total，其次使用本次返回条数）
            const nextHasMore = (typeof t === 'number' && t > 0)
                ? ((page === 1 ? list.length : (items.length + list.length)) < (t || 0))
                : (list.length === PAGE_SIZE);
            setHasMoreOfficial(nextHasMore);
            if (page === 1) initializedOfficialRef.current = true;
        } catch (e) {
            // 仅在当前为最新请求且拉取第一页失败时清空，避免闪烁
            if (currentRequestId === lastRequestIdRef.current) {
                if (page === 1) setItems([]);
                setTotal(0);
            }
        } finally {
            // 仅在当前为最新请求时落下 loading 状态，避免被过期请求覆盖
            if (currentRequestId === lastRequestIdRef.current) setLoading(false);
            fetchingOfficialRef.current = false;
        }
    }, [category, race, page, locale]);

    // 请求函数（我喜欢的）：分页请求我喜欢的角色
    const fetchLikedList = React.useCallback(async () => {
        const currentRequestId = ++lastLikedRequestIdRef.current;
        setLikedLoading(true);
        fetchingLikedRef.current = true;
        try {
            const res = await request.post<ApiListResponse<TemplateItem>>(
                '/api/template/getMyLikedTemplatesRoute',
                {
                    page: likedPage,
                    page_size: PAGE_SIZE,
                    language: toApiLanguageCode(locale as any),
                }
            );
            const { data, total: t = 0 } = res?.data || ({} as any);
            const list = Array.isArray(data) ? data : [];

            if (currentRequestId !== lastLikedRequestIdRef.current) return;

            setLikedItems((prev) => {
                const merged = likedPage === 1 ? list : [...prev, ...list];
                const seen = new Set<string | number>();
                const deduped: TemplateItem[] = [];
                for (const item of merged) {
                    const key = (item.id ?? item.image_url ?? item.name ?? '') as any;
                    if (!seen.has(key)) {
                        seen.add(key);
                        deduped.push(item);
                    }
                }
                return deduped;
            });
            setLikedTotal(t || 0);
            const nextHasMore = (typeof t === 'number' && t > 0)
                ? ((likedPage === 1 ? list.length : (likedItems.length + list.length)) < (t || 0))
                : (list.length === PAGE_SIZE);
            setHasMoreLiked(nextHasMore);
            if (likedPage === 1) initializedLikedRef.current = true;
        } catch (e) {
            if (currentRequestId === lastLikedRequestIdRef.current) {
                if (likedPage === 1) setLikedItems([]);
                setLikedTotal(0);
            }
        } finally {
            if (currentRequestId === lastLikedRequestIdRef.current) setLikedLoading(false);
            fetchingLikedRef.current = false;
        }
    }, [likedPage, locale]);

    // 打开即请求 + 依赖变化时请求
    React.useEffect(() => {
        fetchList();
    }, [fetchList]);

    // 打开即请求“我喜欢的”
    React.useEffect(() => {
        fetchLikedList();
    }, [fetchLikedList]);

    // 点击卡片：回传所需字段并返回生成页
    const handleSelect = (item: TemplateItem) => {
        const state: any = {
            image_url: item?.image_url || '',
            name: item?.name || '',
            id: item?.id,
            role_prompt: item?.role_prompt,
            // 将 category 透传回父组件/路由 state
            category: item?.category,
        };
        // 弹窗模式：回调给父组件
        if (onSelect) {
            onSelect(item);
            if (onClose) onClose();
            return;
        }
        // 路由模式：返回上一页并携带 state
        try {
            // 避免类型报错，直接使用原生 history 返回
            (window.history as History).back();
        } catch {
            navigate('/creatImages', { state });
        }
    };

    // 渲染顶部工具栏（Tab + 筛选）
    const Toolbar = (
        <div className='pt-3 pb-2 sticky top-0 z-10 bg-[#0b0b0b] md:bg-[#0b0b0b]'>
            <div style={{ borderBottom: "1px solid #2C2C2C" }} className=' pb-2 sticky top-0 z-10 bg-[#0b0b0b] md:bg-[#0b0b0b]'>
                <div className='flex items-center relative'>
                    <div className='flex-1 text-[16px] font-semibold text-center'>{t('CreatImg.select_character')}</div>
                    {/* close button */}
                    <button className='ml-2 w-10  text-[2rem] absolute right-3 text-[#e5e7eb]' onClick={() => { if (onClose) onClose(); else { try { (window.history as History).back(); } catch { navigate('/creatImages'); } } }} >
                        {t('loginModel.close')}
                    </button>
                </div>
            </div>
            {/* tabs */}
            <div className='mt-3 px-3'>
                <div className='bg-[#18181A] border border-[#27272A] rounded-lg w-full'>
                    <div className='grid grid-cols-2 gap-1 p-1'>
                        <button
                            onClick={() => setTab('liked')}
                            className={`h-9 rounded-md text-sm flex items-center justify-center w-full ${tab === 'liked' ? 'text-white' : 'text-[#cbd0d5]'}`}
                            style={tab === 'liked' ? { background: 'linear-gradient(to right, rgb(236, 72, 153), rgb(244, 114, 182), rgb(236, 72, 153))' } : undefined}
                        >
                            {t('CreatImgExt.tab_liked')}
                        </button>
                        <button
                            onClick={() => setTab('official')}
                            className={`h-9 rounded-md text-sm flex items-center justify-center w-full ${tab === 'official' ? 'text-white' : 'text-[#cbd0d5]'}`}
                            style={tab === 'official' ? { background: 'linear-gradient(to right, rgb(236, 72, 153), rgb(244, 114, 182), rgb(236, 72, 153))' } : undefined}
                        >
                            {t('CreatImgExt.tab_official')}
                        </button>
                    </div>
                </div>
            </div>
            {/* filter row */}
            {tab === 'official' && (
                <div className='mt-3 px-3  flex'>
                    {/* category */}
                    <div className='mr-2 flex-1'>
                        <div className='h-10 rounded-lg bg-[#18181A] border border-[#27272A] px-3 flex items-center justify-between text-sm text-[#e5e7eb]'>
                            <span>{t('CreatImgExt.all')}</span>
                            <select
                                className='bg-transparent outline-none text-[#e5e7eb]'
                                value={category}
                                onChange={(e) => { setPage(1); setCategory(e.target.value as CategoryType); }}
                            >
                                <option value=''>{t('CreatImgExt.all')}</option>
                                {categoryOptions.map(opt => (
                                    <option key={opt.value} value={opt.value}>{opt.label}</option>
                                ))}
                            </select>
                        </div>
                    </div>
                    {/* race */}
                    <div className='ml-2 flex-1'>
                        <div className='h-10 rounded-lg bg-[#18181A] border border-[#27272A] px-3 flex items-center justify-between text-sm text-[#e5e7eb]'>
                            <span>{t('CreatImgExt.race_person')}</span>
                            <select
                                className='bg-transparent outline-none text-[#e5e7eb]'
                                value={race}
                                onChange={(e) => { setPage(1); setRace(e.target.value as RaceType); }}
                            >
                                <option value=''>{t('CreatImgExt.all')}</option>
                                {raceOptions.map(opt => (
                                    <option key={opt.value} value={opt.value}>{opt.label}</option>
                                ))}
                            </select>
                        </div>
                    </div>
                </div>
            )}
        </div>
    );

    // 当前展示源：根据选项卡切换
    const activeItems = tab === 'liked' ? likedItems : items;
    const activeTotal = tab === 'liked' ? likedTotal : total;
    const activeLoading = tab === 'liked' ? likedLoading : loading;

    // 渲染网格
    const Grid = (
        <div style={{ borderTop: "1px solid #2C2C2C", zIndex: 9999 }} className='px-3 pb-6'>
            {/* 保持网格常驻，减少加载时的闪烁 */}
            {activeLoading && activeItems.length === 0 && (
                <div className='text-center text-[#9ea3a8] py-3'>{t('CreatImg.loading')}</div>
            )}
            <div className='grid mt-3 grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-5 2xl:grid-cols-5 gap-2 md:gap-3 lg:gap-4'>
                {activeItems.map((it, idx) => (
                    <button
                        key={it.id ? String(it.id) : (it.image_url ? `img:${it.image_url}` : (it.name ? `name:${it.name}` : `i:${idx}`))}
                        className='relative rounded-lg overflow-hidden bg-[#111]'
                        onClick={() => handleSelect(it)}
                    >
                        {/* 头像：固定 4:7 比例容器（pt-[175%]），禁止使用 cover，保证图片完整显示 */}
                        <div style={{ aspectRatio: '4 / 7', width: '100%', position: 'relative', backgroundColor: '#111' }} className='flex items-center justify-center'>
                            <img
                                src={(it.image_url || '').trim()}
                                alt={it.name || t('CreatImg.alt_character')}
                                // 保证完整显示，不裁剪
                                className='w-full h-full'
                                style={{ objectFit: 'contain', display: 'block' }}
                                loading='lazy'
                            />
                        </div>
                        {/* 名称 */}
                        <div className='absolute w-full bg-gradient-to-t from-black/60 to-transparent bottom-0  text-center'>
                            <span className='px-2 pb-2 pt-2 text-white text-[0.9rem] font-semibold inline-flex max-w-full' style={{ display: '-webkit-box', WebkitLineClamp: 2 as any, WebkitBoxOrient: 'vertical' as any, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'normal' }}>
                                {it.name || t('my_liked_persion.unnamed_template')}
                            </span>
                        </div>
                    </button>
                ))}
            </div>

            {/* 加载提示 + sentinel 用于 IntersectionObserver 触发懒加载 */}
            <div className='mt-4 flex justify-center items-center text-sm text-[#cbd0d5]'>
                {activeItems.length < activeTotal ? (activeLoading ? t('CreatImg.loading') : t('CreatImg.pull_to_load_more')) : t('CreatImg.no_more')}
            </div>
            <div ref={sentinelRef} style={{ height: 1 }} />
        </div>
    );

    // 当弹窗打开时锁定 body 滚动，防止父容器滚动（同时处理移动端 touchmove）
    React.useEffect(() => {
        const prevOverflow = document.body.style.overflow;
        const prevPaddingRight = document.body.style.paddingRight;
        const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
        if (scrollbarWidth > 0) document.body.style.paddingRight = `${scrollbarWidth}px`;
        document.body.style.overflow = 'hidden';

        // 只在非 modal 区域阻止 touchmove，允许 modal 内部滚动
        const touchHandler = (e: TouchEvent) => {
            const tgt = e.target as Node | null;
            if (scrollRef.current && tgt && scrollRef.current.contains(tgt)) {
                // 在 modal 内容内，允许滚动
                return;
            }
            e.preventDefault();
        };
        document.addEventListener('touchmove', touchHandler as EventListener, { passive: false });

        return () => {
            document.body.style.overflow = prevOverflow;
            document.body.style.paddingRight = prevPaddingRight;
            document.removeEventListener('touchmove', touchHandler as EventListener);
        };
    }, []);

    // 使用 IntersectionObserver 监听底部 sentinel，实现懒加载（比 scroll 事件更可靠）
    React.useEffect(() => {
        const sentinel = sentinelRef.current;
        const root = scrollRef.current;
        if (!sentinel || !root) return;
        const io = new IntersectionObserver((entries) => {
            for (const entry of entries) {
                if (entry.isIntersecting) {
                    const hasMore = (tab === 'liked' ? hasMoreLiked : hasMoreOfficial);
                    const isLoading = tab === 'liked' ? likedLoading : loading;
                    const fetching = tab === 'liked' ? fetchingLikedRef.current : fetchingOfficialRef.current;
                    // 只有在已初始化、存在更多数据、当前未在加载且对应 fetch 标志为 false 时触发翻页
                    const initialized = (tab === 'liked') ? initializedLikedRef.current : initializedOfficialRef.current;
                    if (hasMore && !fetching && initialized && !isLoading) {
                        if (tab === 'liked') {
                            setLikedPage((p) => p + 1);
                        } else {
                            setPage((p) => p + 1);
                        }
                    }
                }
            }
        }, { root, rootMargin: '120px' });
        io.observe(sentinel);
        // 在 IO 建立后立即做一次主动检查，避免 sentinel 已经在可视区域但未触发回调的情况
        tryLoadMore();
        return () => io.disconnect();
    }, [tab, likedItems.length, likedTotal, likedLoading, items.length, total, loading, tryLoadMore]);

    // 当加载状态或数据变化后，再次主动检查一次，保障首屏不足一屏或已在底部时能继续翻页
    React.useEffect(() => {
        tryLoadMore();
    }, [tryLoadMore, tab, loading, likedLoading, items.length, likedItems.length, total, likedTotal, page, likedPage]);

    // 切换筛选时，重置官方初始化标记并回到顶部，不清空 items 以避免闪烁
    React.useEffect(() => {
        initializedOfficialRef.current = false;
        if (scrollRef.current) {
            try { scrollRef.current.scrollTo({ top: 0, behavior: 'auto' }); } catch { }
        }
    }, [category, race]);

    // 切换选项卡时：根据已有数据恢复初始化标志，必要时触发第一页或续页
    React.useEffect(() => {
        if (scrollRef.current) {
            try { scrollRef.current.scrollTo({ top: 0, behavior: 'auto' }); } catch { }
        }
        // 如未加载过第一页则触发加载；若已存在数据则视为已初始化并尝试续页
        if (tab === 'liked') {
            if (likedItems.length === 0 && !likedLoading) {
                setLikedPage(1);
            } else {
                initializedLikedRef.current = true;
                // 切换后若 sentinel 可见则尝试加载更多
                setTimeout(() => { tryLoadMore(); }, 0);
            }
        } else {
            if (items.length === 0 && !loading) {
                setPage(1);
            } else {
                initializedOfficialRef.current = true;
                setTimeout(() => { tryLoadMore(); }, 0);
            }
        }
    }, [tab]);

    return (
        <div style={{ zIndex: 9999 }} className='fixed inset-0 z-50 bg-black/70 flex items-start justify-center md:p-6' onClick={() => { if (onClose) onClose(); }}>
            <div style={{ borderTop: "1px solid #2C2C2C", borderBottom: "1px solid #2C2C2C" }} className='bg-[#0b0b0b] w-[100vw] md:w-[92vw] lg:w-[86vw] xl:w-[80vw] 2xl:w-[70vw] max-w-[1400px] h-[85vh] md:h-[88vh] lg:h-[90vh] mt-2 overflow-hidden flex flex-col rounded-none md:rounded-2xl' onClick={(e) => e.stopPropagation()}>
                {Toolbar}
                <div ref={scrollRef} className='flex-1 overflow-y-auto'>
                    {Grid}
                </div>
            </div>
        </div>
    );
};

export default SelectPersion;


